#include "marketplatform.h"
#include "marketapp.h"
#include <string>
#include <vector>
#include <memory>
#include <atomic>
#include <XStr.h>
#include <XHelper.h>

namespace XTrade {

	MarketThread::MarketThread()
	{
		platform_ = (MarketPlatform*)XPlatformApi::instance();
	}

	int MarketThread::on_run(bool is_join)
	{
		return XThreadSpi::on_run(is_join);
	}

	int MarketThread::on_cmd(int cmd, void* param)
	{
		switch (cmd)
		{
		case EVT_PACKET:
		{
			std::shared_ptr<Msg> msg_ptr;
			if (platform_->pop_request(msg_ptr))
			{
				voidptr data_ptr = iRefFieldData("SH.600000");
				if (data_ptr)
				{
					//
				}
			}
		}
		break;
		}
		return 0;
	}

	MarketPlatform::MarketPlatform():api_(nullptr)
	{

	}

	MarketPlatform::~MarketPlatform()
	{
		
	}

	bool MarketPlatform::start(boost::property_tree::ptree &cfg)
	{
		auto opt_thread = cfg.get_child_optional("thread");
		ASSERT(opt_thread);
		boost::property_tree::ptree & thread_cfg = opt_thread.get();
		BOOST_FOREACH(const boost::property_tree::ptree::value_type &thread_cfg_i, thread_cfg)
		{
			std::string name = thread_cfg_i.second.get<std::string>("name", "");
			if (name.empty())
			{
				continue;
			}
			auto thread_info_ptr = std::make_shared<XThreadInfo>();
			thread_info_ptr->name = name;
			thread_info_ptr->api = nullptr;
			thread_map_[thread_cfg_i.first] = thread_info_ptr;
		}
		evt_thread_.start(boost::bind(&MarketPlatform::run, this));
		return true;
	}

	void MarketPlatform::stop()
	{
		if (api_) {
			api_->post_quit();
		}
		//thread_->join();
		evt_thread_.stop();
	}

	void MarketPlatform::run()
	{
		//boost::filesystem::path app_path = boost::dll::program_location();
		std::string app_name = theApp.name();
		std::string app_work = theApp.work_path().string();
		std::string app_data = theApp.data_path().string();
		api_ = XPlatformApi::instance();
		if (api_) {
			api_->register_spi(this);
			api_->init(app_name.c_str()
				, app_work.c_str()
				, app_data.c_str());
			api_->login("", "");
			api_->run();
			api_->term();
		}
		XPlatformApi::release();
		api_ = nullptr;
	}

	void MarketPlatform::post_request(std::shared_ptr<Msg>& msg)
	{
		req_que_.push(msg);
		XThreadApi* thread = select_thread();
		if (thread) {
			thread->post(EVT_PACKET);
		}
	}

	bool MarketPlatform::pop_request(std::shared_ptr<Msg>& msg)
	{
		return req_que_.pop(msg);
	}

	void MarketPlatform::post_response(std::shared_ptr<Msg>& msg)
	{
		rsp_que_.push(msg);
		//MarketApi
	}

	bool MarketPlatform::pop_response(std::shared_ptr<Msg>& msg)
	{
		return rsp_que_.pop(msg);
	}

	XThreadApi* MarketPlatform::select_thread()
	{
		boost::unique_lock<boost::mutex> lock(thread_mutex_);
		if (thread_it_==thread_map_.end())
		{
			thread_it_ = thread_map_.begin();
		}
		XThreadApi* thread = thread_it_->second->api;
		++thread_it_;
		return thread;
	}

	int MarketPlatform::on_run(bool is_join)
	{
		//printf("MarketPlatform::on_run\n");
		XIndicatorApi* pIndicator = XIndicatorApi::GetInstance();
		if (pIndicator) {
			pIndicator->RegisterQuoteProvider(this);
			pIndicator->RegisterTradeProvider(this);
		}
		for (auto it = thread_map_.begin(); it!=thread_map_.end(); ++it)
		{
			it->second->api = api_->create_thread(it->second->name.c_str());
		}
		int rlt = XPlatformSpi::on_run(is_join);
		for (auto it = thread_map_.begin(); it != thread_map_.end(); ++it)
		{
			api_->destroy_thread(it->second->api);
			it->second->api = nullptr;
		}
		return rlt;
	}

	int MarketPlatform::on_run_thread()
	{
		//printf("MarketPlatform::on_run_thread\n");
		int rlt = XPlatformSpi::on_run_thread();
		//
		return rlt;
	}

}